#ifndef __DYNAMIC_ARRAY_H__
#define __DYNAMIC_ARRAY_H__
#include <assert.h>
#include <stdlib.h>
#include "types.h"

#define DA_INIT_CAPACITY 256

// BEGIN --- Modified from: https://raw.githubusercontent.com/tsoding/musializer/master/nob.h
#define dyn_array_append(da, item) \
    do { \
        if ((da)->length >= (da)->capacity) { \
            (da)->capacity = (da)->capacity == 0 ? DA_INIT_CAPACITY : (da)->capacity*2; \
            (da)->items = realloc((da)->items, (da)->capacity*sizeof(*(da)->items)); \
            assert((da)->items != NULL && "Buy more RAM lol"); \
        } \
        (da)->items[(da)->length++] = (item); \
    } while (0)

#define dyn_array_append_many(da, new_items, new_items_length) \
    do { \
        if ((da)->length + (new_items_length) > (da)->capacity) { \
            if ((da)->capacity == 0) { \
                (da)->capacity = DA_INIT_CAPACITY; \
            } \
            while ((da)->length + (new_items_length) > (da)->capacity) { \
                (da)->capacity *= 2; \
            } \
            (da)->items = realloc((da)->items, (da)->capacity*sizeof(*(da)->items)); \
            assert((da)->items != NULL && "Buy more RAM lol"); \
        } \
        memcpy((da)->items + (da)->length, (new_items), (new_items_length)*sizeof(*(da)->items)); \
        (da)->length += (new_items_length); \
    } while (0)

#define init_array(da) \
    do { \
        (da) = calloc(1, sizeof(*(da))); \
        assert((da) != NULL && "Failed to init da.\n"); \
    } while(0)

#define dyn_array_free(da) free((da).items)
#define reset_free(da) free((da).items); (da).length = 0; (da).capacity = 0;
#define null_free(da) reset_free((da)); (da).items = NULL;
#define empty(da) if((da).length != 0) reset_free(da);

// END --- Modified from: https://raw.githubusercontent.com/tsoding/musializer/master/nob.h

// --- Example generic implementation
// typedef struct dyn_array {
//     void* items;
//     u64 length;
//     u64 capacity;
// } dyn_array_t;
//

#endif // __DYNAMIC_ARRAY_H__